package com.example.flowermall.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.example.flowermall.domain.LoginBody;
import com.example.flowermall.domain.LoginUser;
import com.example.flowermall.entity.Result;
import com.example.flowermall.entity.User;
import com.example.flowermall.mapper.UserMapper;
import com.example.flowermall.service.ILoginService;
import com.example.flowermall.service.IMenuService;
import com.example.flowermall.service.WxService;
import com.example.flowermall.util.JwtUtil;
import com.example.flowermall.util.RedisUtil;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class LoginServiceImpl implements ILoginService {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${wxLogin.appId}")
    private String AppId ;  //公众平台自己的appId
    @Value("${wxLogin.appSecret}")
    private String AppSecret ;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    UserMapper userMapper;
    @Autowired
    IMenuService menuService;
    @Autowired
    WxService wxService;
    @Autowired
    PasswordEncoder passwordEncoder;


    @Override
    public String login(LoginBody loginBody) {
        User user = userMapper.selectUser(loginBody.getUsername());
        if (ObjectUtils.isEmpty(user)) {
            return "用户不存在";
        }
        String code = loginBody.getCode();
        String answer = (String) redisUtil.redisTemplate.opsForValue().get("captcha_code" + loginBody.getUuid());
        if (code.equals(answer)) {
            try {
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword());
                Authentication authenticate = authenticationManager.authenticate(authenticationToken);
                if (ObjectUtils.isEmpty(authenticate)) {
                    return "登录失败";
                }
                LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
                String userId = loginUser.getUser().getId().toString();
                String jwt = JwtUtil.createJWT(userId);
                log.info(jwt);
                redisUtil.setCacheObject("login" + userId, loginUser);
                return jwt;
            }catch (BadCredentialsException e) {
                // 如果密码错误，抛出自定义异常或返回 "密码错误"
                throw new BadCredentialsException("密码错误");
            }
        } else {
            return null;
        }
    }

    @Override
    public String wxlogin(LoginBody loginBody) {
        User user = userMapper.selectUser(loginBody.getUsername());
        if (ObjectUtils.isEmpty(user)) {
            return "用户不存在";
        }
        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword());
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if (ObjectUtils.isEmpty(authenticate)) {
                return "登录失败";
            }
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            String userId = loginUser.getUser().getId().toString();
            String jwt = JwtUtil.createJWT(userId);
            log.info(jwt);
            redisUtil.setCacheObject("login" + userId, loginUser);
            return jwt;
        }catch (BadCredentialsException e) {
            // 如果密码错误，抛出自定义异常或返回 "密码错误"
            throw new BadCredentialsException("密码错误");
        }
    }

    @Override
    public Map<String, Object> getInfo(String token) {
        // List<Menu> menuList = menuService.getMenuListByUserList(user.getId());
        return Result.error("登录失败~");
    }

    @Override
    public void logout(String token) {
        redisUtil.deleteObject(token);
    }

    @Override
    public List<String> getRoleNameByUserId(Integer integer) {
        List<String> name = userMapper.getRoleNameByUserId(integer);
        return name;
    }

    @Override
    public String getSessionId(String code, String encryptedData, String iv) throws Exception {

        String url = "https://api.weixin.qq.com/sns/jscode2session?" +
                "appid=" + AppId +
                "&secret=" + AppSecret +
                "&js_code=" + code +
                "&grant_type=authorization_code";
        String jsonData = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(jsonData);
        //请求返回的是Json类型的数据 所以我们需要用到fastjson
        //这个判断是判断我们的请求是否出错，如果没有出错的话就能够拿到openid
        if (StringUtils.contains(jsonData, "errcode")) {
            //出错了
            return "err";
        }
        String openid = jsonObject.getString("openid");
        String sessionKey = jsonObject.getString("session_key");

        JSONObject jsonObject1 = wxService.wxDecrypt(encryptedData, sessionKey, iv);
        String username = jsonObject1.getString("nickName");
        String gender = jsonObject1.getString("gender");
        String avatarUrl = jsonObject1.getString("avatarUrl");
        switch (gender) {
            case "0":
                gender = null;
                break;
            case "1":
                gender = "男";
                break;
            case "2":
                gender = "女";
                break;
        }
        User user = new User();
        user.setUsername(username);
        user.setAvatar(avatarUrl);
        user.setGender(gender);
        user.setOpenId(openid);
        user.setCreateTime(LocalDateTime.now());
        User user1 = userMapper.selectUserByOpenId(openid);
        if(user1==null){
            userMapper.insert(user);
            LoginUser loginUser = new LoginUser(user);
            String jwt = JwtUtil.createJWT(loginUser.getUser().getId().toString());
            log.info(jwt);
            redisUtil.setCacheObject("login" + loginUser.getUser().getId().toString(), loginUser);
            return jwt;
        }
        LoginUser loginUser = new LoginUser(user1);
        String jwt = JwtUtil.createJWT(loginUser.getUser().getId().toString());
        log.info(jwt);
        redisUtil.setCacheObject("login" + loginUser.getUser().getId().toString(), loginUser);
        return jwt;
    }
}
